package com.googlecode.afx.view.behavior.impl;

import javafx.scene.Node;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.afx.utils.AFXUtils;
import com.googlecode.afx.view.NodeWrapper;
import com.googlecode.afx.view.behavior.ViewCondition;
import com.googlecode.afx.view.validation.ValidationHandler;

public final class ViewConditions {

	private static final Log LOG = LogFactory.getLog(ViewConditions.class);
	
	/**
	 * Applies the given <tt>NodeHandler</tt>, if all values given in <tt>nodesToCheck</tt> are present.
	 * 
	 * @author Martin
	 *
	 * @param <T>
	 */
	public static final class AllValuesProvidedCondition implements ViewCondition {
		
		public boolean meets(Node root, String[] nodesToCheck) {
			boolean result = true;
			if(nodesToCheck != null) {
				for(String id : nodesToCheck) {
					Node node = AFXUtils.findNodeById(root, id);
					if(node == null) {
						LOG.warn("Node with id='" + id + "' does not exist. Assume 'false' as result. Please check your configuration.");
						return false;
					}
					NodeWrapper wrapper = new NodeWrapper(node);
					result &= !AFXUtils.isEmpty(wrapper.getPrimaryValue());
				}
			}
			return result;
		}
	}
	
	/**
	 * Applies the given <tt>NodeHandler</tt>, if at least one value given in <tt>nodesToCheck</tt> is present.
	 * 
	 * @author Martin
	 *
	 * @param <T>
	 */
	public static final class AtLeastOneValueProvidedCondition implements ViewCondition {

		public boolean meets(Node root, String[] nodesToCheck) {
			if(nodesToCheck != null) {
				for(String id : nodesToCheck) {
					Node node = AFXUtils.findNodeById(root, id);
					if(node == null) {
						LOG.warn("Node with id='" + id + "' does not exist. Assume 'false' as result. Please check your configuration.");
						return false;
					}
					NodeWrapper wrapper = new NodeWrapper(node);
					if(!AFXUtils.isEmpty(wrapper.getPrimaryValue())) {
						return true;
					}
				}
			}
			return false;
		}
	}

	/**
	 * Applies the given <tt>NodeHandler</tt>, if at least one value given in <tt>nodesToCheck</tt> is missing.
	 * 
	 * @author Martin
	 *
	 * @param <T>
	 */
	public static final class AtLeastOneValueMissingCondition implements ViewCondition {

		public boolean meets(Node root, String[] nodesToCheck) {
			if(nodesToCheck != null) {
				for(String id : nodesToCheck) {
					Node node = AFXUtils.findNodeById(root, id);
					if(node == null) {
						LOG.warn("Node with id='" + id + "' does not exist. Assume 'false' as result. Please check your configuration.");
						return false;
					}
					NodeWrapper wrapper = new NodeWrapper(node);
					if(AFXUtils.isEmpty(wrapper.getPrimaryValue())) {
						return true;
					}
				}
			}
			return false;
		}
	}

	/**
	 * Applies the given <tt>NodeHandler</tt>, if no values given in <tt>nodesToCheck</tt> are present.
	 * 
	 * @author Martin
	 *
	 * @param <T>
	 */
	public static final class NoValueProvidedCondition implements ViewCondition {

		public boolean meets(Node root, String[] nodesToCheck) {
			boolean result = true;
			if(nodesToCheck != null) {
				for(String id : nodesToCheck) {
					Node node = AFXUtils.findNodeById(root, id);
					if(node == null) {
						LOG.warn("Node with id='" + id + "' does not exist. Assume 'false' as result. Please check your configuration.");
						return false;
					}
					NodeWrapper wrapper = new NodeWrapper(node);
					result &= AFXUtils.isEmpty(wrapper.getPrimaryValue());
				}
			}
			return result;
		}
	}	

	/**
	 * Applies the given <tt>NodeHandler</tt>, if the nodes in <tt>nodesToCheck</tt> have no validation errors.
	 * 
	 * @author Martin
	 *
	 * @param <T>
	 */
	public static final class NoValidationErrorCondition implements ViewCondition {

		private ValidationHandler validationHandler;
		
		public NoValidationErrorCondition(ValidationHandler validationHandler) {
			this.validationHandler = validationHandler;
		}
		
		public boolean meets(Node root, String[] nodesToCheck) {
			boolean result = true;
			if(nodesToCheck != null) {
				for(String id : nodesToCheck) {
					result &= !this.validationHandler.hasValidationErrors(id);
				}
			}
			return result;
		}
	}
	
	/**
	 * Applies the given <tt>NodeHandler</tt>, if the nodes in <tt>nodesToCheck</tt> have validation errors.
	 * 
	 * @author Martin
	 *
	 * @param <T>
	 */
	public static final class ValidationErrorCondition implements ViewCondition {

		private ValidationHandler validationHandler;
		
		public ValidationErrorCondition(ValidationHandler validationHandler) {
			this.validationHandler = validationHandler;
		}
		
		public boolean meets(Node root, String[] nodesToCheck) {
			if(nodesToCheck != null) {
				for(String id : nodesToCheck) {
					if(this.validationHandler.hasValidationErrors(id)) {
						return true;
					}
				}
			}
			return false;
		}
	}
	
}
